// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com

// ReSharper disable CheckNamespace
// ReSharper disable ClassNeverInstantiated.Global
// ReSharper disable CommentTypo
// ReSharper disable IdentifierTypo
// ReSharper disable InconsistentNaming
// ReSharper disable StringLiteralTypo
// ReSharper disable UnusedParameter.Local

/*
 * Ars Magna project, http://arsmagna.ru
 */

#region Using directives

using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;

#endregion

#nullable enable

namespace AM.Reporting.Data
{
    /// <summary>
    /// Represents the collection of system variables.
    /// </summary>
    public class SystemVariables : ParameterCollection
    {
        internal SystemVariables (Base owner) : base (owner)
        {
            Add (new DateVariable());
            Add (new PageVariable());
            Add (new TotalPagesVariable());
            Add (new PageNVariable());
            Add (new PageNofMVariable());
            Add (new RowVariable());
            Add (new AbsRowVariable());
            Add (new PageMacroVariable());
            Add (new TotalPagesMacroVariable());
            Add (new CopyNameMacroVariable());
            Add (new HierarchyLevelVariable());
            Add (new HierarchyRowNoVariable());
        }
    }


    /// <summary>
    /// Represents the base class for system variables.
    /// </summary>
    public class SystemVariable : Parameter
    {
        /// <summary>
        /// This property is not relevant to this class.
        /// </summary>
        [Browsable (false)]
        public new string Expression
        {
            get => base.Expression;
            set => base.Expression = value;
        }

        /// <summary>
        /// This property is not relevant to this class.
        /// </summary>
        [Browsable (false)]
        public new string Description
        {
            get => base.Description;
            set => base.Description = value;
        }

        /// <inheritdoc/>
        public override bool CanContain (Base child)
        {
            return false;
        }
    }

    /// <summary>
    /// Returns date and time of the report's start.
    /// </summary>
    public class DateVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => Report.Engine.Date;

        internal DateVariable()
        {
            Name = "Date";
            DataType = typeof (DateTime);
        }
    }

    /// <summary>
    /// Returns current page number.
    /// </summary>
    public class PageVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => Report.Engine.PageNo;

        internal PageVariable()
        {
            Name = "Page";
            DataType = typeof (int);
        }
    }

    /// <summary>
    /// Returns total number of pages in the report. To use this variable, you need
    /// to enable the report's double pass.
    /// </summary>
    public class TotalPagesVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => Report.Engine.TotalPages;

        internal TotalPagesVariable()
        {
            Name = "TotalPages";
            DataType = typeof (int);
        }
    }

    /// <summary>
    /// Returns a string containing the current page number in a form "Page N".
    /// </summary>
    public class PageNVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => Report.Engine.PageN;

        internal PageNVariable()
        {
            Name = "PageN";
            DataType = typeof (string);
        }
    }

    /// <summary>
    /// Returns a string containing the current page number and total pages in a form "Page N of M".
    /// To use this variable, you need to enable the report's double pass.
    /// </summary>
    public class PageNofMVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => Report.Engine.PageNofM;

        internal PageNofMVariable()
        {
            Name = "PageNofM";
            DataType = typeof (string);
        }
    }

    /// <summary>
    /// Returns data row number inside the group. This value is reset at the start of a new group.
    /// </summary>
    public class RowVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => Report.Engine.RowNo;

        internal RowVariable()
        {
            Name = "Row#";
            DataType = typeof (int);
        }
    }

    /// <summary>
    /// Returns absolute number of data row. This value is never reset at the start of a new group.
    /// </summary>
    public class AbsRowVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => Report.Engine.AbsRowNo;

        internal AbsRowVariable()
        {
            Name = "AbsRow#";
            DataType = typeof (int);
        }
    }

    /// <summary>
    /// Returns current page number.
    /// <para/>This variable is actually a macro. Its value is substituted when the component is viewed in
    /// the preview window. That means you cannot use it in an expression.
    /// </summary>
    public class PageMacroVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => "[PAGE#]";

        internal PageMacroVariable()
        {
            Name = "Page#";
            DataType = typeof (int);
        }
    }

    /// <summary>
    /// Returns the number of total pages in the report.
    /// <para/>This variable is actually a macro. Its value is substituted when the component is viewed in
    /// the preview window. That means you cannot use it in an expression.
    /// </summary>
    public class TotalPagesMacroVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => "[TOTALPAGES#]";

        internal TotalPagesMacroVariable()
        {
            Name = "TotalPages#";
            DataType = typeof (int);
        }
    }

    /// <summary>
    /// Returns the name of the printed copy.
    /// <para/>This variable is actually a macro. Its value is substituted when the component is viewed in
    /// the preview window. That means you cannot use it in an expression.
    /// </summary>
    public class CopyNameMacroVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => "[COPYNAME#]";

        internal CopyNameMacroVariable()
        {
            Name = "CopyName#";
            DataType = typeof (string);
        }
    }

    /// <summary>
    /// Returns a level of hierarchy in the hierarchical report.
    /// </summary>
    public class HierarchyLevelVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => Report.Engine.HierarchyLevel;

        internal HierarchyLevelVariable()
        {
            Name = "HierarchyLevel";
            DataType = typeof (int);
        }
    }

    /// <summary>
    /// Returns the row number like "1.2.1" in the hierarchical report.
    /// </summary>
    public class HierarchyRowNoVariable : SystemVariable
    {
        /// <inheritdoc/>
        public override object Value => Report.Engine.HierarchyRowNo;

        internal HierarchyRowNoVariable()
        {
            Name = "HierarchyRow#";
            DataType = typeof (string);
        }
    }
}
